package com.htd.apm.Controller;

import com.alibaba.fastjson.JSONObject;
import com.htd.htdapmapi.alarm.dto.AlarmMessageDto;
import com.htd.htdapmapi.alarm.dto.AlertsDto;
import com.htd.htdapmapi.alarm.dto.LabelsDto;
import com.htd.htdapmapi.alarm.dto.PrometheusDto;
import com.htd.htdapmapi.alarm.dto.ZabbixDto;
import com.htd.htdapmapi.alarm.request.AlarmInto;
import com.htd.htdapmapi.alarm.result.AlarmResult;
import com.htd.htdapmapi.common.CommonResult;
import com.htd.htdapmcommon.constants.AlarmConstants;
import com.htd.htdapmcommon.enums.AlarmsLevelEnum;
import com.htd.htdapmcommon.enums.AlarmsStatusEnum;
import com.htd.htdapmcommon.util.DateUtil;
import com.htd.htdapmcommon.util.ExecuteResult;
import com.htd.htdapmservice.request.SearchAlarmInto;
import com.htd.htdapmservice.result.ResponseAlarmInfo;
import com.htd.htdapmservice.service.intf.OneAlertService;

import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/htdAlarm")
public class AlarmController {

	private static final Logger logger = LoggerFactory.getLogger(AlarmController.class);

	@Resource
	private TransportClient client;
	@Autowired
	private OneAlertService oneAlertService;


	/**
	 * 接受外部告警状态信息
	 * @param responseAlarmInfo
	 * @return
	 */
	@RequestMapping(value = "/receiveNotice", method = RequestMethod.POST)
	public String receiveNotice(@RequestBody ResponseAlarmInfo responseAlarmInfo) {
		logger.info("接收到通知信息为{}", responseAlarmInfo);
		CommonResult res = new CommonResult();
		try {
			// 只对状态为接收、关闭的告警，进行处理
			if(responseAlarmInfo != null && (AlarmsStatusEnum.ACK.getCode().equals(responseAlarmInfo.getStatus())
					|| AlarmsStatusEnum.CLOSED.getCode().equals(responseAlarmInfo.getStatus()))){
				// 更新es、mysql状态
				res = oneAlertService.updateAlarmStatus(responseAlarmInfo);
				if(res == null || !"0000".equals(res.getResponseCode())){
					logger.info("更新状态失败，alarmsId为{}", responseAlarmInfo.getAlarmId());
					return "fail";
				}
			}
		} catch (Exception e) {
			logger.error("receiveNotice接口异常，", e);
		}
		return "ok";
	}



	
	private String getALertInfo(List<AlertsDto> alerts){
		
		if(CollectionUtils.isEmpty(alerts)){
			return "";
		}
		String alertName=alerts.get(0).getLabels().getAlertname();
		StringBuffer buffer = new StringBuffer(alertName);
		for(AlertsDto dto: alerts){
			LabelsDto labels = dto.getLabels();
			if(labels !=null){
				buffer.append("|").append(labels.getInstance());
			}
		}
		return buffer.toString();
	}



	// 更新ES根据ID
	@RequestMapping(value = "/updateAlarm", method = RequestMethod.POST)
	public UpdateResponse updateAlarm(String alarmId, String alarmStatus) {
		UpdateResponse updateResponse = new UpdateResponse();
		logger.info("更新告警数据告警ID为:{},告警状态:{}", alarmId, alarmStatus);
		try {
			GetResponse getResponse = client
					.prepareGet(AlarmConstants.SKYWALKING_INDEX_NAME, AlarmConstants.SKYWALKING_TYPE_NAME, alarmId)
					.execute().actionGet();
			if (!getResponse.isExists()) {
				logger.info("告警ID为:{},的告警信息不存在", alarmId);
				return updateResponse;
			}
			UpdateRequest request = new UpdateRequest(AlarmConstants.SKYWALKING_INDEX_NAME,
					AlarmConstants.SKYWALKING_TYPE_NAME, alarmId);
			XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
			if (alarmStatus != null) {
				builder.field("alarmStatus", alarmStatus);
			}
			builder.endObject();
			request.doc(builder);
			updateResponse = client.update(request).get();

		} catch (Exception e) {
			logger.error("更新告警数据失败:", e);
		}
		return updateResponse;
	}

	// 更新ES根据ID
	@RequestMapping(value = "/queryAlarm", method = RequestMethod.POST)
	public GetResponse queryAlarm(String alarmId) {
		logger.info("告警ID为:{}", alarmId);
		GetResponse getResponse = null;
		try {
			getResponse = client
					.prepareGet(AlarmConstants.SKYWALKING_INDEX_NAME, AlarmConstants.SKYWALKING_TYPE_NAME, alarmId)
					.execute().actionGet();
			if (!getResponse.isExists()) {
				logger.info("告警ID为:{},的告警信息不存在", alarmId);
				return getResponse;
			}
		} catch (Exception e) {
			logger.error("查询告警数据失败:", e);
		}
		return getResponse;
	}

	/**
	 * 发送skywalking告警信息
	 * 
	 */
	private void sendAlarm(AlarmMessageDto dto) {
		try {
			AlarmInto alarmInto = new AlarmInto();
			alarmInto.setEventType(AlarmsStatusEnum.ALARM_TRIGGER.getCode());
			alarmInto.setPriority(AlarmsLevelEnum.LEVEL_TWO.getCode());
			alarmInto.setProductType(AlarmConstants.TYPE_SKYWALKING);
			alarmInto.setAlarmsDetail(dto.getAlarmMessage());
			alarmInto.setAlarmsTitle(dto.getName());
			alarmInto.setAlarmsId(dto.getAlarmsId());
			AlarmResult alarmResult = oneAlertService.createAlarm(alarmInto);
			logger.info("调用告警接口返回{}： ", alarmResult);
		} catch (Exception e) {
			logger.error("发送告警信息失败:", e);
		}
	}

	/**
	 * 发送Prometheus告警信息
	 * 
	 */
	private void sendPrometheusAlarm(PrometheusDto dto) {
		try {
			AlarmInto alarmInto = new AlarmInto();
			alarmInto.setEventType(dto.getEventType());
			alarmInto.setPriority(AlarmsLevelEnum.LEVEL_TWO.getCode());
			alarmInto.setProductType(AlarmConstants.TYPE_PROMETHEUS);
			List<AlertsDto> alerts = dto.getAlerts();
			if (!CollectionUtils.isEmpty(alerts)) {
				if (alerts.get(0).getAnnotations() != null) {
					alarmInto.setAlarmsDetail(alerts.get(0).getAnnotations().getDescription());
					alarmInto.setAlarmsTitle(alerts.get(0).getAnnotations().getSummary());
				}
			}
			alarmInto.setAlarmsId(dto.getAlarmsId());
			AlarmResult alarmResult = oneAlertService.createAlarm(alarmInto);
			logger.info("调用告警接口返回{}： ", alarmResult);
		} catch (Exception e) {
			logger.error("发送告警信息失败:", e);
		}
	}

	@RequestMapping(value = "/test", method = RequestMethod.POST)
	public void test() {
		SearchAlarmInto searchAlarmInto = new SearchAlarmInto();
		searchAlarmInto.setStatus("ACK,CLOSED");
		oneAlertService.searchAlarm(searchAlarmInto);
	}
	
	
	@RequestMapping(value = "/updateES", method = RequestMethod.POST)
	public UpdateResponse updateES(String indexName,String typeName, String alarmId,String alarmStatus) throws Exception {
		UpdateResponse updateResponse = new UpdateResponse();
		GetResponse getResponse =getES(indexName, typeName, alarmId);
		UpdateRequest  updateRequest =null;
		if(getResponse !=null && getResponse.isExists()){
			 updateRequest = new UpdateRequest(indexName, typeName, alarmId); 
		}
		if(updateRequest !=null){
			XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
			if (alarmStatus != null) {
				builder.field("alarmStatus", alarmStatus);
			}
			builder.endObject();
			updateRequest.doc(builder);
			updateResponse = client.update(updateRequest).get();
			logger.info("更新ES结果:{}",updateResponse.getResult());
		}
		return updateResponse;
	}
	
	
	
	// 创建索引+存储数据
	@RequestMapping(value = "/addZabbixAlarmMessage", method = RequestMethod.POST)
	public ExecuteResult<IndexResponse> addZabbixAlarmMessage(@RequestBody ZabbixDto zabbixDto) {
		logger.info("Zabbix告警数据:{}", zabbixDto);
		ExecuteResult<IndexResponse>  rs = new ExecuteResult<IndexResponse> ();
		IndexResponse response = null;
		try {
			if (zabbixDto ==null) {
				logger.info("Zabbix告警数据为空!");
				rs.addErrorMessage("Zabbix告警数据为空!");
				return rs;
			}
			String id = zabbixDto.getEntityId();
			if(StringUtils.isBlank(id)){
				logger.info("Zabbix告警数据id为空!");
				rs.addErrorMessage("Zabbix告警id为空!");
				return rs;
			}
			zabbixDto.setAlarmTime(DateUtil.getTime4ES());
			zabbixDto.setAlarmStatus(AlarmsStatusEnum.ACTIVE.getCode());
			zabbixDto.setAlarmsId(id);
			zabbixDto.setSourceFrom(AlarmConstants.SOURCE_FROM_3);
			sendZabbixAlarm(zabbixDto);
			GetResponse getResponse =getES(AlarmConstants.ZABBIX_INDEX_NAME, AlarmConstants.ZABBIX_TYPE_NAME, id);
			if(getResponse !=null && getResponse.isExists()){
				updateElasticsearch(JSONObject.toJSONString(zabbixDto),AlarmConstants.ZABBIX_INDEX_NAME, AlarmConstants.ZABBIX_TYPE_NAME, id);
				rs.setResultMessage("更新了zabbix:告警id为:"+id);
				logger.info("更新了zabbix:告警id为:{}",id);
			}
		} catch (Exception e) {
			logger.error("告警数据失败:", e);
		}
		return rs;
	}
	
	

	/**
	 * 发送zabbix告警信息
	 * 
	 */
	private void sendZabbixAlarm(ZabbixDto dto) {
		try {
			AlarmInto alarmInto = new AlarmInto();
			alarmInto.setApp(dto.getApp());
			alarmInto.setEventType(dto.getEventType());
			alarmInto.setPriority(dto.getPriority());
			alarmInto.setProductType(AlarmConstants.TYPE_ZABBIX);
			alarmInto.setAlarmsDetail(dto.getAlarmContent());
			alarmInto.setAlarmsTitle(dto.getAlarmName());
			alarmInto.setAlarmsId(dto.getAlarmsId());
			AlarmResult alarmResult = oneAlertService.createAlarm(alarmInto);
			logger.info("调用告警接口返回{}： ", alarmResult);
		} catch (Exception e) {
			logger.error("发送告警信息失败:", e);
		}
	}
	
	

	//获取入参
	@RequestMapping(value = "/getReqParam", method = RequestMethod.POST)
	public void getReqParam(String param) {
		logger.info("入参:{}",param);
	}
	
	//获取ES 告警数据
	private GetResponse getES( String alarmIndex,String alarmType,String alarmId){
		GetResponse getResponse = client.prepareGet(alarmIndex,alarmType, alarmId).execute().actionGet();
		return getResponse;
	}
	
	private UpdateResponse updateElasticsearch(String dtoString,String indexName,String typeName,String alarmID){
		UpdateResponse updateResponse = new UpdateResponse();
		try {
			UpdateRequest  updateRequest = new UpdateRequest(indexName,typeName, alarmID); 
			updateRequest.doc(dtoString, XContentType.JSON); //整体更新
			updateResponse = client.update(updateRequest).get();
		} catch (Exception e) {
			logger.error("更新ES失败:", e);
		} 
		return updateResponse;
	}
	


}
